// $Id: Rules.cs 18 2007-04-26 13:19:49Z mcartoixa $

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Salamanca.DataRules;

namespace Salamanca.NUnit.DataRules
{

    internal class MockAddress:
        Validatable
    {

        protected override IList<IRule> CreateRules()
        {
            IList<IRule> ret=base.CreateRules();

            ret.Add(
                new ValidationDelegationRule<MockAddress>(
                    "City",
                    "The city must be valid",
                    City,
                    string.Empty
                )
            );

            return ret;
        }

        [NotNullRule]
        public MockCity City
        {
            get
            {
                return _City;
            }
            set
            {
                _City=value;
            }
        }

        private MockCity _City=new MockCity();
    }

    internal class MockCity:
        Validatable
    {

        protected override IList<IRule> CreateRules()
        {
            IList<IRule> ret=base.CreateRules();

            ret.Add(
                new PredicateRule<MockCity>(
                    "The zip code must not be null",
                    new Predicate<MockCity>(
                        delegate(MockCity c) {
                            return c.ZipCode!=null;
                        }
                    )
                )
            );

            ret.Add(
                new PredicateRule<MockCity>(
                    "The city name must not be null",
                    new Predicate<MockCity>(
                        delegate(MockCity c) {
                            return c.Name!=null;
                        }
                    )
                )
            );

            ret.Add(
                new PredicateRule<MockCity>(
                    "Name",
                    "The city name must have at least one character.",
                    new Predicate<MockCity>(
                        delegate(MockCity c) {
                            return (c.Name==null)||(c.Name.Length>0);
                        }
                    )
                )
            );

            return ret;
        }

        [RegexRule(@"^(\d{5}-\d{4})|(\d{5})$", Description="This is not a valid US Zip code.")]
        public string ZipCode
        {
            get
            {
                return _ZipCode;
            }
            set
            {
                _ZipCode=value;
            }
        }

        [NotNullRule]
        public object Data
        {
            get
            {
                return _Data;
            }
            set
            {
                _Data=value;
            }
        }

        public string Name
        {
            get
            {
                return _Name;
            }
            set
            {
                _Name=value;
            }
        }

        private string _Name;
        private string _ZipCode;
        private object _Data;
    }

    [TestClass]
    public class RulesFixture
    {
        [TestMethod]
        public void CanValidateAttributeNotNullRule()
        {
            MockCity c=new MockCity();
            Assert.IsFalse(c.Validate("Data"));

            c.Data=new object();
            Assert.IsTrue(c.Validate("Data"));
        }

        [TestMethod]
        public void CanValidateAttributeRegexRule()
        {
            MockCity c=new MockCity();
            Assert.IsTrue(c.Validate("ZipCode"));

            // Invalid zip code
            c.ZipCode="abcdef";
            Assert.IsFalse(c.Validate("ZipCode"));

            // Valid zip code
            c.ZipCode="12345";
            Assert.IsTrue(c.Validate("ZipCode"));
        }

        [TestMethod]
        public void CanValidatePredicateRule()
        {
            MockCity c=new MockCity();
            Assert.IsTrue(c.Validate("Name"));

            // Invalid name
            c.Name=string.Empty;
            Assert.IsFalse(c.Validate("Name"));

            // Valid name
            c.Name="Test";
            Assert.IsTrue(c.Validate("Name"));
        }

        [TestMethod]
        public void CanValidateAllRules()
        {
            MockCity c=new MockCity();
            Assert.IsFalse(c.Validate());

            c.Data=new object();
            Assert.IsFalse(c.Validate());

            c.ZipCode="12345";
            Assert.IsFalse(c.Validate());

            c.Name="Test";
            Assert.IsTrue(c.Validate());
        }

        [TestMethod]
        public void CanValidateValidationDelegationRule()
        {
            MockAddress a=new MockAddress();
            Assert.IsFalse(a.Validate("City"));

            a.City.Data=new object();
            Assert.IsFalse(a.Validate("City"));

            a.City.ZipCode="12345";
            Assert.IsFalse(a.Validate("City"));

            a.City.Name="Test";
            Assert.IsTrue(a.Validate("City"));
        }

    }
}
